﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    // 委托 引用类型，表示对具有特定参数列表和返回类型的方法的引用
    // 委托特别适用于实现事件和回调方法，所有的委托都派生自 System.Delegate 类。委托允许将方法作为参数进行传递；
    internal class DemoDelegate
    {
        static FileStream fs;
        static StreamWriter sw;

        // 委托声明
        public delegate void printString(string s);

        // 该方法打印到控制台
        public static void WriteToScreen(string str)
        {
            Console.WriteLine("The String is: {0}", str);
        }

        // 该方法打印到文件
        public static void WriteToFile(string s)
        {
            fs = new FileStream("./message.txt", FileMode.Append, FileAccess.Write);
            sw = new StreamWriter(fs);
            sw.WriteLine(s);
            sw.Flush();
            sw.Close();
            fs.Close();
        }

        // 该方法把委托作为参数，并使用它调用方法
        public static void sendString(printString ps)
        {
            ps("C语言中文网");
        }

        static void Main(string[] args)
        {
            // 实例化委托对象并将其与 WriteToScreen 方法关联
            printString ps1 = new printString(WriteToScreen);
            printString ps2 = new printString(WriteToFile);
            sendString(ps1);
            sendString(ps2);
            Console.ReadKey();
        }
        
        //Func<T> 是一个泛型委托，表示返回值的方法。它有一个出参数和零或更多输入参数，并且必须返回一个值。最后一个参数被视为返回参数。
        //用途: 1、定义匿名方法或Lambda表达式。2、其作为参数传递给其他方法。
        void Demo1()
        {
            //1、带有一个参数
            Func<int, int> Squaring = s => s * s;
            int result = Squaring(4);
            Console.WriteLine("平方为：{0}", result);
            
            //2、具有多个参数
            Func<float, float, float> Summation = (x, y) => x + y;
            float sum = Summation(5.2f, 6);
            Console.WriteLine("和为：{0}", sum);
            
            //3、没有参数
            Func<string> getCurrentTime = () => DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            string now = getCurrentTime();
            Console.WriteLine("输出时间：{0}", now);
        }
        
        //Action<T> 是一个泛型委托，表示执行操作但不返回值的方法。它有零或更多输入参数，但没有返回值
        //用途: 1、无需返回值即可执行操作。2、记录或打印消息。3、事件处理。
        void Demo2()
        {
            //1、带有一个参数
            Action<string> printMessage = message => Console.WriteLine(message);
            printMessage("执行Action委托");
            
            //2、具有多个参数
            Action<int, int> printSum = (x, y) => Console.WriteLine("计算和：{0}",x + y);
            printSum(5, 10);
            
            //3、没有参数
            Action displayTime = () => Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            displayTime();
        }
        
        //Predicate<T> 委托定义一个接受一个输入参数并返回布尔值的方法。它通常用于过滤或条件检查。是Func的一个特例，专门用于返回布尔值的情况。它通常用于定义过滤条件。
        //用途: 1、过滤集合。2、条件检查。3、验证逻辑。
        void Demo3()
        {
            //1、只有一个参数
            Predicate<int> isEven = x => x % 2 ==0;
            var even = isEven(16);
            Console.WriteLine("是否为偶数：{0}", even);
            
            var fruits = new List<string> { "apple", "banana", "cherry", "date", "elderberry" };
            Predicate<string> startsWithB = s => s.StartsWith("b", StringComparison.OrdinalIgnoreCase);    
            var bFruit = fruits.Find(startsWithB);
            Console.WriteLine(bFruit);
        }
        
        public delegate void Notify();  // 声明委托  
  
        public class ProcessBusinessLogic  
        {  
            public event Notify ProcessCompleted;  // 使用委托声明事件  
  
            public void StartProcess()  
            {  
                Console.WriteLine("Process Started!");  
                // 模拟一些处理任务  
                System.Threading.Thread.Sleep(3000);  
  
                // 处理完成后触发事件  
                OnProcessCompleted();  
            }  
  
            protected virtual void OnProcessCompleted()  
            {  
                ProcessCompleted?.Invoke();  
            }  
        }  
        
        // 1、简单回调机制
        static void Demo4()  
        {  
            ProcessBusinessLogic bl = new ProcessBusinessLogic();  
            bl.ProcessCompleted += Bl_ProcessCompleted;  // 订阅事件  
            bl.StartProcess();  
        }  
  
        private static void Bl_ProcessCompleted()  
        {  
            Console.WriteLine("Process Completed!");  
        }
        
        // 2、多播委托
        static void Demo5()
        {
            Notify notify = Method1;  
            notify += Method2;  // 订阅多个方法  
  
            notify();  
        }
        
        public static void Method1()  
        {  
            Console.WriteLine("Method1 invoked.");  
        }  
  
        public static void Method2()  
        {  
            Console.WriteLine("Method2 invoked.");  
        }

        // 3.匿名方法和Lambda表达式
        public delegate void Print(int value);  
        static void Demo6()
        {
            Print print = delegate(int val) {  
                Console.WriteLine("Anonymous method: {0}", val);  
            };  
  
            print(100);  
  
            print = (val) => Console.WriteLine("Lambda expression: {0}", val);  
  
            print(200);  
        }
        
        // 4.事件处理 (WPF)
        
        // 5、函数式编程
        static void Demo7()
        {
            List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };  
            List<int> evenNumbers = numbers.Where(n => n % 2 == 0).ToList();//Where方法接受一个委托Func<int, bool>来筛选列表中的偶数
  
            evenNumbers.ForEach(n => Console.WriteLine(n));  
        }
    }
}
